﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Pyramid.Hardware.Gates;

namespace Pyramid.Hardware.Operations
{
    public abstract class Operation
    {
        private IEnumerable<ILine> _inputBusA;
        private IEnumerable<ILine> _inputBusB;

        private readonly ILine defaultOverflowFlag = FixedInputLine.Unknown;
        private ILine signFlag;

        protected Operation(IEnumerable<ILine> inputBusA, IEnumerable<ILine> inputBusB)
        {
            if (inputBusA == null)
                throw new ArgumentNullException("inputBusA");

            if (inputBusB == null)
                throw new ArgumentNullException("inputBusB");

            Debug.Assert(inputBusA.Count() == inputBusB.Count());

            _inputBusA = inputBusA;
            _inputBusB = inputBusB;
        }

        protected IEnumerable<ILine> InputBusA
        {
            get
            {
                return _inputBusA;
            }
        }

        protected IEnumerable<ILine> InputBusB
        {
            get
            {
                return _inputBusB;
            }
        }

        public abstract IEnumerable<ILine> OutputBus
        {
            get;
        }

        public virtual ILine OverflowFlag
        {
            get
            {
                return this.defaultOverflowFlag;
            }
        }

        public virtual ILine SignFlag
        {
            get
            {
                if (this.signFlag == null)
                {
                    var outputList = OutputBus.ToList();

                    var lastSign = outputList[0];

                    for (int lineIndex = 1; lineIndex < outputList.Count; lineIndex++)
                    {
                        lastSign = new PrecedenceGate(outputList[lineIndex], lastSign);
                    }

                    this.signFlag = lastSign;
                }

                return this.signFlag;
            }
        }
    }
}
